﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.Web.Mvc.ModelBinding;
using System.Reflection;

namespace MvcApplicationBindersSample.Binders {
    public class ImmutableObjectModelBinderProvider : ModelBinderProvider {

        public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext) {
            if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) {
                // the value provider can't give us anything for this model
                return null;
            }

            // there must be a single public constructor
            ConstructorInfo[] candidateCtors = bindingContext.ModelType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
            if (candidateCtors.Length != 1) {
                return null;
            }

            // the constructor must be parameterful
            ConstructorInfo ctor = candidateCtors[0];
            ParameterInfo[] ctorParameters = ctor.GetParameters();
            if (ctorParameters.Length == 0) {
                return null;
            }

            // all constructor parameters must have corresponding property metadatas
            foreach (ParameterInfo pInfo in ctorParameters) {
                ModelMetadata propertyMetadata;
                bindingContext.PropertyMetadata.TryGetValue(pInfo.Name, out propertyMetadata);
                if (propertyMetadata == null || propertyMetadata.ModelType != pInfo.ParameterType) {
                    return null; // property not found or type didn't match
                }
            }

            // all checks passed
            return new ImmutableObjectModelBinder();
        }

    }
}
